﻿using AutoMapper;
using Compass.PurchaseService.Domain;
using Compass.PurchaseService.Domain.Entities;
using Compass.PurchaseService.Infrastructure;
using Compass.Wasm.Shared;
using Compass.Wasm.Shared.Purchases;

namespace Compass.Wasm.Server.Services.Purchases;
public interface INavInvValuationService:IBaseService<NavInvValuationDto>
{
    Task<ApiResponse<NavInvValuationDto>> GetSingleByNumberAndMonthAsync(string number,DateTime month);
    Task<ApiResponse<IEnumerable<NavInvValuationDto>>> GetAllByNumberAndPeriodAsync(string number,DateTime start, DateTime end);
    Task<ApiResponse<IEnumerable<NavMonthlyValuationDto>>> GetMonthlyValuationsAsync();
}
public class NavInvValuationService:INavInvValuationService
{
    #region ctor
    private readonly PurchaseDbContext _dbContext;
    private readonly IPurchaseRepository _repository;
    private readonly IMapper _mapper;
    public NavInvValuationService(PurchaseDbContext dbContext, IPurchaseRepository repository, IMapper mapper)
    {
        _dbContext = dbContext;
        _repository = repository;
        _mapper = mapper;
    } 
    #endregion

    #region 基本增删改查
    public async Task<ApiResponse<IEnumerable<NavInvValuationDto>>> GetAllAsync()
    {
        try
        {
            var models = await _repository.GetNavInvValuationsAsync();
            //按照料号排序
            var dtos = await _mapper.ProjectTo<NavInvValuationDto>(models).OrderBy(x => x.Number).ToListAsync();
            return new ApiResponse<IEnumerable<NavInvValuationDto>> { Status = true, Result = dtos };
        }
        catch (Exception e)
        {
            return new ApiResponse<IEnumerable<NavInvValuationDto>> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<NavInvValuationDto>> GetSingleAsync(Guid id)
    {
        try
        {
            var model = await _repository.GetNavInvValuationByIdAsync(id);
            if (model == null) return new ApiResponse<NavInvValuationDto> { Status = false, Message = "查询数据失败" };
            var dto = _mapper.Map<NavInvValuationDto>(model);
            return new ApiResponse<NavInvValuationDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<NavInvValuationDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<NavInvValuationDto>> AddAsync(NavInvValuationDto dto)
    {
        try
        {
            var model = new NavInvValuation(Guid.NewGuid(), dto.Number.ToUpper(), dto.YearMonth,dto.IncreaseQuantity,dto.IncreaseValue,dto.DecreasesQuantity,dto.DecreasesValue);
            await _dbContext.NavInvValuations.AddAsync(model);
            dto.Id = model.Id;
            return new ApiResponse<NavInvValuationDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<NavInvValuationDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<NavInvValuationDto>> UpdateAsync(Guid id, NavInvValuationDto dto)
    {
        try
        {
            var model = await _repository.GetNavInvValuationByIdAsync(id);
            if (model == null) return new ApiResponse<NavInvValuationDto> { Status = false, Message = "更新数据失败" };
            model.Update(dto);
            return new ApiResponse<NavInvValuationDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<NavInvValuationDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<NavInvValuationDto>> DeleteAsync(Guid id)
    {
        try
        {
            var model = await _repository.GetNavInvValuationByIdAsync(id);
            if (model == null) return new ApiResponse<NavInvValuationDto> { Status = false, Message = "删除数据失败" };
            model.SoftDelete();//软删除
            return new ApiResponse<NavInvValuationDto> { Status = true };
        }
        catch (Exception e)
        {
            return new ApiResponse<NavInvValuationDto> { Status = false, Message = e.Message };
        }
    }
    #endregion

    #region 扩展查询

    public async Task<ApiResponse<NavInvValuationDto>> GetSingleByNumberAndMonthAsync(string number, DateTime month)
    {
        try
        {
            var model = await _repository.GetNavInvValuationByNumberAndMonthAsync(number,month);
            if (model == null) return new ApiResponse<NavInvValuationDto> { Status = false, Message = "查询数据失败" };
            var dto = _mapper.Map<NavInvValuationDto>(model);
            return new ApiResponse<NavInvValuationDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<NavInvValuationDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<IEnumerable<NavInvValuationDto>>> GetAllByNumberAndPeriodAsync(string number,DateTime start, DateTime end)
    {
        try
        {
            var models = await _repository.GetNavInvValuationsByNumberAndPeriodAsync(number, start, end);

            var dtos = await _mapper.ProjectTo<NavInvValuationDto>(models).ToListAsync();
            return new ApiResponse<IEnumerable<NavInvValuationDto>> { Status = true, Result = dtos };
        }
        catch (Exception e)
        {
            return new ApiResponse<IEnumerable<NavInvValuationDto>> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<IEnumerable<NavMonthlyValuationDto>>> GetMonthlyValuationsAsync()
    {
        try
        {
            var fsItems =await _repository.GetNavItemsByFsAndShareAsync();
            var dtos=new List<NavMonthlyValuationDto>();
            foreach (var item in fsItems)
            {
                var dto = new NavMonthlyValuationDto
                {
                    Number = item.Number,
                    Start = item.Number[..2],
                    Sbu = item.Sbu,
                    Description = item.Description,
                    Unit = item.Unit,
                    UnitCost = Math.Round(item.UnitCost,2),
                    Inventory = Math.Round(item.Inventory,2),
                    InvValue = Math.Round(item.UnitCost * item.Inventory),
                    SafetyStock = item.SafetyStock,
                    SsValue = Math.Round(item.UnitCost * item.SafetyStock),
                    OpenPo=item.OpenPo,
                    OpenPoValue = Math.Round(item.UnitCost * item.OpenPo),
                    NavInvValuationDtos = new List<NavInvValuationDto>()
                };
                //上个月最后一天
                var end = DateTime.Today.AddDays(1 - DateTime.Today.Day).AddDays(-1);
                //往前推12个月
                var start = end.AddMonths(-11);
                var result = await GetAllByNumberAndPeriodAsync(dto.Number, start, end);
                Task.WaitAll();
                for (var i = 0; i < 12; i++)
                {
                    var curMonth = start.AddMonths(i);
                    var invValuationDto = result.Result.SingleOrDefault(x =>
                        x.YearMonth.Year == curMonth.Year &&
                        x.YearMonth.Month == curMonth.Month);
                    dto.NavInvValuationDtos.Add(invValuationDto ?? new NavInvValuationDto
                    {
                        Number = dto.Number,
                        YearMonth = start.AddMonths(i)
                    });
                }

                //Cons
                dto.ConsFrequency = dto.NavInvValuationDtos.Count(x => x.DecreasesQuantity != 0);
                dto.ConsAvg12 =Math.Round(dto.NavInvValuationDtos.Average(x => x.DecreasesQuantity), 2);
                dto.ConsAvg12Value =Math.Round(dto.NavInvValuationDtos.Average(x => x.DecreasesValue), 2);
                dto.ConsAvg6 =Math.Round(dto.NavInvValuationDtos.Skip(6).Average(x => x.DecreasesQuantity), 2);
                dto.ConsAvg3 =Math.Round(dto.NavInvValuationDtos.Skip(9).Average(x => x.DecreasesQuantity), 2);
                //Recv
                dto.RecvFrequency =dto.NavInvValuationDtos.Count(x => x.IncreaseQuantity != 0);
                dto.RecvAvg12 =Math.Round(dto.NavInvValuationDtos.Average(x => x.IncreaseQuantity), 2);
                dto.RecvAvg12Value =Math.Round(dto.NavInvValuationDtos.Average(x => x.IncreaseValue), 2);
                dto.RecvAvg6 =Math.Round(dto.NavInvValuationDtos.Skip(6).Average(x => x.IncreaseQuantity), 2);
                dto.RecvAvg3 = Math.Round(dto.NavInvValuationDtos.Skip(9).Average(x => x.IncreaseQuantity), 2);

                //计算MTPT
                dto.MTPT =dto.ConsAvg12Value==0?0:(int)Math.Ceiling(30d * dto.InvValue / dto.ConsAvg12Value);
                dtos.Add(dto);
            }
            return new ApiResponse<IEnumerable<NavMonthlyValuationDto>> { Status = true, Result = dtos };
        }
        catch (Exception e)
        {
            return new ApiResponse<IEnumerable<NavMonthlyValuationDto>> { Status = false, Message = e.Message };
        }
    }

    #endregion
}